using System;
using System.Linq;
using System.Text.RegularExpressions;
using gudusoft.gsqlparser;
using MongoDB;
using SkynetMongoDBAccess.Converter;

namespace SkynetMongoDBAccess;

internal class ConvertSql
{
	public object? ConvertSelect(string? text, MongoDatabase db)
	{
		text = text.Replace(Environment.NewLine, " ").Replace("\n", " ").Replace("\r", " ");
		int num = text.IndexOf("select", StringComparison.CurrentCultureIgnoreCase);
		int num2 = text.IndexOf("from", StringComparison.CurrentCultureIgnoreCase);
		int num3 = text.IndexOf("where", StringComparison.CurrentCultureIgnoreCase);
		int num4 = text.IndexOf("order by", StringComparison.CurrentCultureIgnoreCase);
		if (num == -1 || num2 == -1)
		{
			throw new Exception("命令错误");
		}
		num += 6;
		num2 += 4;
		string empty = string.Empty;
		if (num3 == -1)
		{
			empty = text.Substring(num2).Trim();
		}
		else
		{
			num3 += 5;
			empty = text.Substring(num2, num3 - num2).Trim();
		}
		string text2 = text.Substring(num, num2 - num).Trim();
		IQueryable<Document> source = db.GetCollection(empty).Linq();
		string[] array = text2.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries);
		for (int i = 0; i < array.Length; i++)
		{
			if (array[i].ToLower().Contains("count"))
			{
				return source.Count();
			}
			if (array[i].Contains("*"))
			{
				return source.ToList().ConvertToDataSet();
			}
			if (array[i].ToLower().StartsWith("top"))
			{
				int count = Convert.ToInt32(array[i].Split(new string[1] { " " }, StringSplitOptions.RemoveEmptyEntries)[1]);
				source = source.Take(count);
			}
		}
		if (num4 > 0)
		{
			num4 += 8;
			string text3 = text.Substring(num4).Trim();
			string[] array2 = text3.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries);
			for (int j = 0; j < array2.Count(); j++)
			{
				string s = array2[j];
				if (s.ToLower().IndexOf(" desc", StringComparison.InvariantCultureIgnoreCase) > 0)
				{
					s = Regex.Replace(s, " desc", "", RegexOptions.IgnoreCase);
					source = source.OrderByDescending((Document o) => o[s]);
				}
				else
				{
					s = Regex.Replace(s, " asc", "", RegexOptions.IgnoreCase);
					source = source.OrderBy((Document o) => o[s]);
				}
			}
		}
		return source.ToList().ConvertToDataSet();
	}

	public void ConvertUpdate(string? text, MongoDatabase db)
	{
		TGSqlParser tGSqlParser = new TGSqlParser(TDbVendor.DbVMssql);
		tGSqlParser.SqlText.Text = text;
		tGSqlParser.Parse();
		if (tGSqlParser.ErrorCount > 0)
		{
			throw new Exception(tGSqlParser.ErrorMessages);
		}
		TUpdateSqlStatement tUpdateSqlStatement = tGSqlParser.SqlStatements[0] as TUpdateSqlStatement;
		ChangeSqlToJs(tUpdateSqlStatement.WhereClause);
		IMongoCollection collection = db.GetCollection(tUpdateSqlStatement.Tables[0].AsText);
		Document document = new Document();
		for (int i = 0; i < tUpdateSqlStatement.Fields.Count(); i++)
		{
			string key = tUpdateSqlStatement.Fields[i].AsText.Split('=')[0].Trim();
			string text2 = tUpdateSqlStatement.Fields[i].AsText.Split('=')[1].Trim();
			if (text2.StartsWith("'"))
			{
				if (DateTime.TryParse(text2.Replace("'", ""), out var result))
				{
					document.Add(key, result);
				}
				else
				{
					document.Add(key, text2.Replace("'", ""));
				}
			}
			else
			{
				int result2 = 0;
				if (int.TryParse(text2, out result2))
				{
					document.Add(key, result2);
				}
				else
				{
					document.Add(key, text2);
				}
			}
			Document document2 = new Document();
			if (!string.IsNullOrEmpty(tUpdateSqlStatement.WhereClauseAsPrettyText))
			{
				document2.Add("$where", new Code(tUpdateSqlStatement.WhereClauseAsPrettyText.Replace("\r\n", "")));
			}
			collection.UpdateAll(document, document2);
		}
	}

	public void ConvertDelete(string? text, MongoDatabase db)
	{
		TGSqlParser tGSqlParser = new TGSqlParser(TDbVendor.DbVMssql);
		tGSqlParser.SqlText.Text = text;
		tGSqlParser.Parse();
		if (tGSqlParser.ErrorCount > 0)
		{
			throw new Exception(tGSqlParser.ErrorMessages);
		}
		TDeleteSqlStatement tDeleteSqlStatement = tGSqlParser.SqlStatements[0] as TDeleteSqlStatement;
		ChangeSqlToJs(tDeleteSqlStatement.WhereClause);
		IMongoCollection collection = db.GetCollection(tDeleteSqlStatement.Tables[0].AsText);
		Document document = new Document();
		if (!string.IsNullOrEmpty(tDeleteSqlStatement.WhereClauseAsPrettyText))
		{
			document.Add("$where", new Code(tDeleteSqlStatement.WhereClauseAsPrettyText.Replace("\r\n", "")));
		}
		collection.Delete(document);
	}

	public void ConvertInsert(string? text, MongoDatabase db)
	{
		TGSqlParser tGSqlParser = new TGSqlParser(TDbVendor.DbVMssql);
		tGSqlParser.SqlText.Text = text;
		tGSqlParser.Parse();
		if (tGSqlParser.ErrorCount > 0)
		{
			throw new Exception(tGSqlParser.ErrorMessages);
		}
		TInsertSqlStatement tInsertSqlStatement = tGSqlParser.SqlStatements[0] as TInsertSqlStatement;
		IMongoCollection collection = db.GetCollection(tInsertSqlStatement.Tables[0].AsText);
		Document document = new Document();
		for (int i = 0; i < tInsertSqlStatement.Fields.Count(); i++)
		{
			string asText = tInsertSqlStatement.Fields[i].AsText;
			string asText2 = (tInsertSqlStatement.MultiValues[0] as TLzFieldList)[i].AsText;
			if (asText2.StartsWith("'"))
			{
				if (DateTime.TryParse(asText2.Replace("'", ""), out var result))
				{
					document.Add(asText, result);
				}
				else
				{
					document.Add(asText, asText2.Replace("'", ""));
				}
			}
			else
			{
				int result2 = 0;
				if (int.TryParse(asText2, out result2))
				{
					document.Add(asText, result2);
				}
				else
				{
					document.Add(asText, asText2);
				}
			}
			collection.Insert(document);
		}
	}

	private void ChangeSqlToJs(TLzCustomExpression pExpr)
	{
		pExpr?.PreOrderTraverse(ChangeSqlToJsVisitor);
	}

	private bool ChangeSqlToJsVisitor(TLz_Node pnode, bool pIsLeafNode)
	{
		TLzCustomExpression tLzCustomExpression = (TLzCustomExpression)pnode;
		if (tLzCustomExpression.oper == TLzOpType.Expr_AND)
		{
			tLzCustomExpression.opname.AsText = "&&";
		}
		else if (tLzCustomExpression.oper == TLzOpType.Expr_Comparison)
		{
			if (tLzCustomExpression.opname.AsText == "=")
			{
				tLzCustomExpression.opname.AsText = "==";
			}
			if (tLzCustomExpression.opname.AsText == "<>")
			{
				tLzCustomExpression.opname.AsText = "!=";
			}
		}
		else if (tLzCustomExpression.oper == TLzOpType.Expr_OR)
		{
			tLzCustomExpression.opname.AsText = "||";
		}
		else if (tLzCustomExpression.oper == TLzOpType.Expr_Attr)
		{
			tLzCustomExpression.AsText = "this." + tLzCustomExpression.AsText;
		}
		return true;
	}
}
